package com.winchain.chainbill.bill.biz.discount.rx;

import com.shell.bee.acct.account.po.AcctBas;
import com.shell.bee.acct.account.po.AcctBkp;
import com.shell.bee.acct.account.util.VirtualAcctUtil;
import com.shell.bee.acct.transaction.po.AcctTxRec;
import com.shell.bee.acct.transaction.vo.AcctInfo;
import com.shell.bee.base.exception.UnCheckException;
import com.shell.bee.base.exception.UnCheckMsgException;
import com.shell.bee.base.utils.DateUtil;
import com.shell.bee.base.utils.MoneyUtil;
import com.shell.bee.base.utils.SpringContextUtil;
import com.shell.bee.base.utils.StringUtil;
import com.shell.bee.base.utils.SystemUtil;
import com.shell.constant.rel.AssetCode;
import com.shell.framework.rx.OnErrorNotImplementedSubscriber;
import com.shell.framework.utils.MathsUtil;
import com.shell.framework.utils.SysDateUtil;
import com.winchain.chainbill.ChainBillUtil;
import com.winchain.chainbill.bill.base.po.CbDct;
import com.winchain.chainbill.bill.base.po.CbRec;
import com.winchain.chainbill.bill.base.service.CbDctService;
import com.winchain.chainbill.bill.biz.Bill;
import com.winchain.chainbill.bill.biz.BillEvent;
import com.winchain.chainbill.trade.service.BillAcctBlcService;
import com.winchain.chainbill.trade.service.BillAcctService;
import com.winchain.chainbill.trade.service.TradeService;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class BillDctPmtPassSubscriber extends OnErrorNotImplementedSubscriber<BillEvent<CbDct>> {
	@Autowired
	private CbDctService cbDctService;
	@Autowired
	private TradeService tradeService;
	@Autowired
	private BillAcctService billAcctService;
	@Autowired
	private BillAcctBlcService billAcctBlcService;

	public void onApplicationEvent(BillEvent<CbDct> t) {
		Bill<CbDct> record = t.getBill();
		CbRec cbRec = record.getRec();
		CbDct cbDct = (CbDct) record.getSource();
		if (cbDct != null) {
			cbDct.setOptSeq(cbRec.getOptSeq());
			reCalDctInt(cbDct, t);
			this.cbDctService.saveOrUpdate(cbDct);
			String grpId = cbRec.getGrpId();
			AcctTxRec tran = getAcctTxRec(cbDct, grpId);
			if ((ChainBillUtil.onlinePay()) && (VirtualAcctUtil.onVirtual())) {
				AcctInfo acctInfo = new AcctInfo();
				acctInfo.setAcctNo(tran.getTxAcctNo());
				acctInfo.setAcctType("1");
				acctInfo.setCurrCode(AssetCode.CNY.name());
				acctInfo.setBkpPrdCode(grpId);
				AcctInfo bas = this.billAcctService.getAcctCardInfo(acctInfo);
				BigDecimal availableAmt = bas.getAvailableAmt();
				if (availableAmt.compareTo(tran.getTxAmt()) < 0) {
					throw new UnCheckMsgException("��������������������������������");
				}
				Map<String, String> ret = this.tradeService.fire(tran);
				if (!"S".equals(ret.get("ret_code"))) {
					throw new UnCheckException("����������" + (String) ret.get("ret_msg"));
				}
			} else {
				this.tradeService.callback(tran);
			}
		}
	}

	private void reCalDctInt(CbDct dct, BillEvent<CbDct> t) {
		BigDecimal dctAmt = dct.getDctAmt();
		if (dct.getDctRatio() != null) {
			dctAmt = dctAmt.multiply(dct.getDctRatio()).divide(MoneyUtil.HUNDRED, 2, RoundingMode.HALF_UP);
		}
		String payDate = SysDateUtil.getSystemDate();
		String expDate = dct.getExpDate();

		String pmtDate = t.getStringValue("pmtDate");
		if (!StringUtil.emptyAndNull(pmtDate)) {
			payDate = pmtDate;
		}
		int dctDays = SysDateUtil.getDaysBetween(payDate, expDate);
		String dctDayStr = t.getStringValue("dctDays");
		if (!StringUtil.emptyAndNull(dctDayStr)) {
			dctDays = Integer.valueOf(dctDayStr).intValue();
		}
		BigDecimal fixedRate = dct.getFixedRate();
		BigDecimal varRate = dct.getVarRate();
		BigDecimal entVarRate = dct.getEntVarRate();
		BigDecimal rate = fixedRate.add(varRate).add(entVarRate);

		BigDecimal dctInt = MathsUtil.mathDctInterest(dctAmt, rate, dctDays, "2");

		Object gint = t.getValue("dctInt");
		if (gint != null) {
			dctInt = new BigDecimal(gint.toString());
		}
		Object recvAmt = t.getValue("recvAmt");
		if (recvAmt != null) {
			dct.setRecvAmt(new BigDecimal(recvAmt.toString()));
		} else if (dct.getDctRatio() != null) {
			dct.setRecvAmt(
					dct.getDctAmt().multiply(dct.getDctRatio()).multiply(new BigDecimal("0.01")).subtract(dctInt));
		} else {
			dct.setRecvAmt(dct.getDctAmt().subtract(dctInt));
		}
		dct.setDctInt(dctInt);
		dct.setPmtDate(payDate);
		dct.setDctDays(Integer.valueOf(dctDays));
		dct.setDctState("2");
		dct.setPmtState("1");
	}

	private AcctTxRec getAcctTxRec(CbDct cbDct, String grpId) {
		if ((!ChainBillUtil.onlinePay()) || (!VirtualAcctUtil.onVirtual())) {
			grpId = null;
		}
		BigDecimal txAmt = cbDct.getActualAmt();

		AcctTxRec txRec = new AcctTxRec();
		txRec.setTxId(SystemUtil.getUUID());
		txRec.setTxSn(txRec.getTxId());
		txRec.setTxAmt(txAmt);
		txRec.setTxDt(DateUtil.getSystemDate());
		txRec.setTxTs(DateUtil.getSystemDateTime());
		txRec.setTxAbs("�������� - ������������");
		txRec.setTxType("cb_dct_pay");

		String sourceCode = SpringContextUtil.getProperty("system.code");
		txRec.setSrcCode(sourceCode);
		txRec.setBizId(cbDct.getBillId());
		txRec.setDataScLvl("B");
		txRec.setTxCashFlag("N");
		txRec.setTxReqFiCls("1");
		txRec.setTxOperator("System");
		txRec.setCurrCode(AssetCode.CNY.name());
		txRec.setTxChnCode("B");

		txRec.setOptType("qt_trd");

		txRec.setTxSts("I");

		AcctBas txAcct = this.billAcctService.getAcctBas(cbDct.getFinId(), null, "00");
		txRec.setTxAcctNo(txAcct.getAcctNo());
		txRec.setTxAcctNm(txAcct.getAcctNm());
		txRec.setTxBankNm(txAcct.getFiNm());

		AcctBas cpAcct = this.billAcctService.getCard(cbDct.getSellerAcct());

		txRec.setCpAcctNo(cpAcct.getAcctNo());
		txRec.setCpAcctNm(cpAcct.getAcctNm());
		txRec.setCpBankNm(cpAcct.getFiNm());

		AcctBkp txAcctBkp = this.billAcctBlcService.getAcctBkp(txRec.getTxAcctNo(), txRec.getCurrCode(), grpId, null);
		txRec.setTxBkpId(txAcctBkp.getBkpId());
		AcctBkp cpAcctBkp = this.billAcctBlcService.getAcctBkp(txRec.getCpAcctNo(), txRec.getCurrCode(), grpId, null);
		txRec.setCpBkpId(cpAcctBkp.getBkpId());
		return txRec;
	}
}
